/*
 * Copyrignt (c) xuzeshui.com. All Rights Reserved.
 * Author: Zeshui Xu<i@xuzeshui.com>
 * Created Time: 2016-04-19 10:52:12
 * Last Modified: 2016-08-26 21:01:42
 * File Name: filmvideo/filmvideo.go
 * Description:
 */
package filmvideo

import (
	"errors"
	"sort"
	"time"

	"advertoper/db"

	"doubimeizhi.com/datatable"
	"doubimeizhi.com/jsonq"
	"doubimeizhi.com/utility"

	log "github.com/cihub/seelog"
)

var (
	filmvideoData map[int64]*FileVideoInfo
	seqMedias     []*MediaSeqItem
)

type FileVideoInfo struct {
	MediaId      int64  `json:"media_id"`
	Seq          int    `json:"seq"`
	PicURL       string `json:"pic_url"`
	MediaType    int    `json:"media_type"`
	CategoryId   int    `json:"category_id"`
	CategoryName string `json:"category_name"`
	InsertTick   int64  `json:"insert_tick"`
	UpdateTick   int64  `json:"update_tick"`
}

func (p *FileVideoInfo) Clone() *FileVideoInfo {
	ti := &FileVideoInfo{}
	ti.MediaId = p.MediaId
	ti.Seq = p.Seq
	ti.PicURL = p.PicURL
	ti.MediaType = p.MediaType
	ti.CategoryId = p.CategoryId
	ti.CategoryName = p.CategoryName
	ti.InsertTick = p.InsertTick
	ti.UpdateTick = p.UpdateTick
	return ti
}

//查询媒体信息列表
func ListMediaInfo(start, length int) []*FileVideoInfo {
	if seqMedias == nil || filmvideoData == nil {
		return make([]*FileVideoInfo, 0, 0)
	}
	res := make([]*FileVideoInfo, 0, length)
	for i := start; i < start+length && i < len(seqMedias); i++ {
		mediaId := seqMedias[i].MediaId
		if ti, ok := filmvideoData[mediaId]; ok {
			res = append(res, ti)
		}
	}
	return res
}

//录入信息
func InsertFileVideoInfo(ti *FileVideoInfo) error {
	if ti.MediaId == 0 {
		_, ti.MediaId = ApplyNewMediaId()
	}
	data := make(map[string]*utility.MySQLFieldValue)
	data["media_id"] = utility.NewMySQLFieldValue(ti.MediaId, false)
	data["media_type"] = utility.NewMySQLFieldValue(ti.MediaType, false)
	data["seq"] = utility.NewMySQLFieldValue(ti.Seq, false)
	data["pic_url"] = utility.NewMySQLFieldValue(ti.PicURL, false)
	data["category_id"] = utility.NewMySQLFieldValue(ti.CategoryId, false)
	data["category_name"] = utility.NewMySQLFieldValue(ti.CategoryName, false)
	if ti.InsertTick == 0 {
		ti.InsertTick = time.Now().Unix()
	}
	data["insert_tick"] = utility.NewMySQLFieldValue(ti.InsertTick, false)
	if ti.UpdateTick == 0 {
		ti.UpdateTick = time.Now().Unix()
	}
	data["update_tick"] = utility.NewMySQLFieldValue(ti.UpdateTick, false)
	mysqlHelper := db.GetMysqlHelper()
	_, err := mysqlHelper.SaveRecord(data, "filmvideo")
	if err == nil {
		filmvideoData[ti.MediaId] = ti
		go calcMediaSeq()
	}
	return err
}

//修改信息
func UpdateFileVideoInfo(tidata map[string]interface{}) error {
	jq := jsonq.NewQuery(tidata)
	data := make(map[string]*utility.MySQLFieldValue)
	var ti *FileVideoInfo
	if mediaId, err := jq.Int("media_id"); err == nil {
		data["media_id"] = utility.NewMySQLFieldValue(int64(mediaId), false)
		val := GetFileVideoInfo(int64(mediaId))
		if val == nil {
			return errors.New("No Exists media_id")
		}
		ti = val.Clone()
	} else {
		return err
	}

	if mediaType, err := jq.Int("media_type"); err == nil && mediaType != ti.MediaType {
		data["media_type"] = utility.NewMySQLFieldValue(mediaType, true)
		ti.MediaType = mediaType
	}

	var seqChanged bool = false

	if seq, err := jq.Int("seq"); err == nil && seq != ti.Seq {
		data["seq"] = utility.NewMySQLFieldValue(seq, true)
		ti.Seq = seq
		seqChanged = true
	}

	if picURL, err := jq.String("pic_url"); err == nil && picURL != ti.PicURL {
		data["pic_url"] = utility.NewMySQLFieldValue(picURL, true)
		ti.PicURL = picURL
	}

	if categoryId, err := jq.Int("category_id"); err == nil && categoryId != ti.CategoryId {
		data["category_id"] = utility.NewMySQLFieldValue(categoryId, true)
		ti.CategoryId = categoryId
	}

	if categoryName, err := jq.String("category_name"); err == nil && categoryName != ti.CategoryName {
		data["category_name"] = utility.NewMySQLFieldValue(categoryName, true)
		ti.CategoryName = categoryName
	}

	data["update_tick"] = utility.NewMySQLFieldValue(time.Now().Unix(), true)
	ti.UpdateTick = time.Now().Unix()
	if len(data) <= 2 {
		return nil
	}
	mysqlHelper := db.GetMysqlHelper()
	_, err := mysqlHelper.SaveRecord(data, "filmvideo")
	if err == nil {
		filmvideoData[ti.MediaId] = ti
		if seqChanged {
			go calcMediaSeq()
		}
	}
	return err
}

//创建datatable.DataTableQuery对象
func createDataTableForFileVideoInfo() *datatable.DataTableQuery {
	dtq := datatable.NewDataTableQuery()
	dtq.SetTableName("filmvideo")
	dtq.PushField(&datatable.FiledItem{Alias: "media_id", Field: "media_id"})
	dtq.PushField(&datatable.FiledItem{Alias: "media_type", Field: "media_type"})
	dtq.PushField(&datatable.FiledItem{Alias: "seq", Field: "seq"})
	dtq.PushField(&datatable.FiledItem{Alias: "pic_url", Field: "pic_url"})
	dtq.PushField(&datatable.FiledItem{Alias: "category_id", Field: "category_id"})
	dtq.PushField(&datatable.FiledItem{Alias: "category_name", Field: "category_name"})
	dtq.PushField(&datatable.FiledItem{Alias: "insert_tick", Field: "insert_tick"})
	dtq.PushField(&datatable.FiledItem{Alias: "update_tick", Field: "update_tick"})
	return dtq
}

func parseRowRecordForFileVideoInfo(dt map[string]interface{}, mysqlHelper *utility.MySQLHelper) *FileVideoInfo {
	ti := &FileVideoInfo{}
	ti.MediaId = mysqlHelper.GetColInt64(dt, "media_id")
	ti.MediaType = mysqlHelper.GetColInt(dt, "media_type")
	ti.Seq = mysqlHelper.GetColInt(dt, "seq")
	ti.PicURL = mysqlHelper.GetColString(dt, "pic_url")
	ti.CategoryId = mysqlHelper.GetColInt(dt, "category_id")
	ti.CategoryName = mysqlHelper.GetColString(dt, "category_name")
	ti.InsertTick = mysqlHelper.GetColInt64(dt, "insert_tick")
	ti.UpdateTick = mysqlHelper.GetColInt64(dt, "update_tick")
	return ti
}

//查询列表
func ListFileVideoInfo(start, length int, conditions map[string]interface{}, needTotalRecords bool) ([]*FileVideoInfo, int) {
	dtq := createDataTableForFileVideoInfo()
	dtq.SetPage(start, length)
	if conditions != nil {
		for key, val := range conditions {
			dtq.PushCondition(key, val)
		}
	}
	sql, values := dtq.GenerateSQL()
	data := make([]*FileVideoInfo, 0, length)
	mysqlHelper := db.GetMysqlHelper()
	if results, err := mysqlHelper.Query(sql, values...); err == nil {
		for _, dt := range results {
			data = append(data, parseRowRecordForFileVideoInfo(dt, mysqlHelper))
		}
	}
	recordsTotal := 0
	if needTotalRecords {
		sql1, val1 := dtq.GenerateTotalRecordSQL("recordsTotal")
		recordsTotal = mysqlHelper.GetRecordCount("recordsTotal", sql1, val1...)
	}
	return data, recordsTotal
}

func GetFileVideoInfo(mediaId int64) *FileVideoInfo {
	if filmvideoData == nil {
		return nil
	}
	if ti, ok := filmvideoData[mediaId]; ok {
		return ti
	}
	return nil
}

func DeleteFileVideoInfo(mediaId int64) error {
	if filmvideoData == nil {
		return nil
	}
	_, ok := filmvideoData[mediaId]
	if !ok {
		return nil
	}
	dtd := datatable.NewDataTableDelete()
	dtd.SetTableName("filmvideo")
	dtd.PushCondition("media_id = ?", mediaId)
	sql, values := dtd.GenerateSQL()
	mysqlHelper := db.GetMysqlHelper()
	if _, err := mysqlHelper.Exec(sql, values...); err != nil {
		log.Warnf("DeleteFileVideoInfo error: %s, values: %v", err.Error(), values)
		return err
	}
	delete(filmvideoData, mediaId)
	go calcMediaSeq()
	return nil
}

func LoadFileVideoInfo2Mem() {
	start := 0
	length := 1000
	data := make(map[int64]*FileVideoInfo)
	for {
		tis, _ := ListFileVideoInfo(start, length, nil, false)
		for _, ti := range tis {
			data[ti.MediaId] = ti
		}
		if len(tis) < length {
			break
		}
		start = start + length
	}
	filmvideoData = data
	go calcMediaSeq()
}

//计算媒体的seq顺序,按media_id排序
func calcMediaSeq() {
	if filmvideoData == nil {
		return
	}
	seqs := make([]*MediaSeqItem, 0, len(filmvideoData))
	for _, ti := range filmvideoData {
		seqs = append(seqs, &MediaSeqItem{MediaId: ti.MediaId, Seq: ti.Seq})
	}
	sort.Sort(byMediaSeq(seqs))
	seqMedias = seqs
}

type MediaSeqItem struct {
	MediaId int64
	Seq     int
}

type byMediaSeq []*MediaSeqItem

func (p byMediaSeq) Len() int {
	return len(p)
}

func (p byMediaSeq) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}

func (p byMediaSeq) Less(i, j int) bool {
	return p[i].Seq < p[j].Seq
}
